package com.example.springboot.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


/**
 * Redis发布订阅
 */
@Configuration
public class RedisConfig {

	private RedisConnectionFactory redisConnectionFactory;

	@Autowired
	public RedisConfig(RedisConnectionFactory redisConnectionFactory) {
		this.redisConnectionFactory = redisConnectionFactory;
	}

	@Bean
	public MessageListener listener() {
		return new SubscribeListener();
	}

	/**
	 * 发布订阅的topic
	 * @return
	 */
	@Bean
	public ChannelTopic channelTopic() {
		return new ChannelTopic("vote-detail");
	}

	/**
	 * 按模式匹配
	 * @return
	 */
	@Bean
	public PatternTopic patternTopic() {
		return new PatternTopic("/vote/detail");
	}

	/**
	 * 将消息监听绑定到消息容器
	 * @return
	 */
	@Bean
	public RedisMessageListenerContainer messageListenerContainer() {
		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(redisConnectionFactory);
		// 可以修改成 patternTopic, 看一看 MessageListener 中监听的数据
		container.addMessageListener(listener(), channelTopic());
		return container;
	}

	/**
	 * redis模板，存储关键字是字符串，值是Jdk序列化
	 * @param factory
	 * @return
	 * @Description:
	 */
	@Bean
	public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(factory);
		//key序列化方式;但是如果方法上有Long等非String类型的话，会报类型转换错误；
		RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
		redisTemplate.setKeySerializer(redisSerializer);
		redisTemplate.setHashKeySerializer(redisSerializer);

		//默认使用JdkSerializationRedisSerializer序列化方式;会出现乱码，改成StringRedisSerializer
		StringRedisSerializer stringSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(stringSerializer);
		redisTemplate.setValueSerializer(stringSerializer);
		redisTemplate.setHashKeySerializer(stringSerializer);
		redisTemplate.setHashValueSerializer(stringSerializer);
		return redisTemplate;
	}

}
